/**
 * 根据选择器查找满足条件的第一个元素
 */
// function $(selector) {
//   return document.querySelector(selector)
// }

/**
 * 获取元素的 css 属性值
 */
function css(element, name) {
  return getComputedStyle(element, null)[name]
}

/**
 * 多属性运动函数
 * @param element 待运动的元素
 * @param options 多属性选项对象，如：{top: 100, left: 200, width: 300, opacity: 1}
 * @param duration 限定运动时长，可选，未传递，默认为 400ms
 * @param fn 函数，运动结束后继续执行的函数
 */
function animate(element, options, duration = 400, fn) {
  // 为 duration 赋默认值
  // duration = duration || 400

  // 先将元素上已有的运动动画效果停止
  clearInterval(element.timer)

  // 计算运动起点值 {top: 0, left: 100, width: 100}
  const start = {}
  // 1ms 的运动距离
  const speed = {}
  // 遍历 options 对象各属性，计算各属性起点与单位时间运动距离
  for (const key in options) {
    start[key] = parseFloat(css(element, key))
    speed[key] = (options[key] - start[key]) / duration
  }

  // 记录运动起始时间
  const startTime = Date.now()
  // 启动定时器，实现运动
  // 将定时器 id 缓存在运动的DOM对象上
  element.timer = setInterval(function() {
    // 计算实际运动时间
    const elapsed = Math.min(duration, Date.now() - startTime)
    // 遍历 options 各属性，计算当前步骤值
    for(const key in options) {
      // 计算实际运动距离
      const distance = elapsed * speed[key]
      // 设置 css 样式
      element.style[key] = start[key] + distance + (key === 'opacity' ? '' : 'px')
    }
    // 判断是否运动到达终点，如果到达终点，则停止定时器
    if (elapsed === duration) {
      clearInterval(element.timer)
      // 运动结束后，如果有需要继续执行的函数，则调用执行
      fn && fn()
    }
  }, 1000 / 60)
}

// /**
//  * 淡入
//  * @param element 待运动的元素
//  * @param duration 限定运动时长
//  * @param fn 函数，运动结束后继续执行的函数
//  */
function fadeIn(element, duration = 400, fn) {
  element.style.display = 'block'
  element.style.opacity = 0
  animate(element, {opacity: 1}, duration, fn)
}

// /**
//  * 淡出
//  * @param element 待运动的元素
//  * @param duration 限定运动时长
//  * @param fn 函数，运动结束后继续执行的函数
//  */
 function fadeOut(element, duration = 400, fn) {
  animate(element, {opacity: 0}, duration, function() {
    element.style.display = 'none'
    fn && fn()
  })
}
